'use strict';

/**
 *
 * @param input : 1,2,3,4
 * @returns obj.query = (?,?,?,?) obj.params = [1,2,3,4]
 */
function prepareInClauseParams(input) {

  let inElems = input.split(',')
  let obj = {}
  obj.whereQuery = ''
  obj.whereParams = []

  for (var j = 0; j < inElems.length; ++j) {

    if (j === 0) {
      //enclose with open parenthesis
      obj.whereQuery += '('
    }
    if (j) {
      obj.whereQuery += ','
    }
    // add q mark and push the variable
    obj.whereQuery += '?'
    obj.whereParams.push(inElems[j])

    if (j === inElems.length - 1) {
      //enclose with closing parenthesis
      obj.whereQuery += ')'
    }
  }

  //console.log(obj);

  return obj

}

function prepareLikeValue(value) {

  //return value.replace("~", "%");
  return value.replace(/~/g, '%');

}

function prepareIsValue(value) {

  //return value.replace("~", "%");
  if (value === 'null') {
    return null;
  } else if (value === 'true') {
    return true;
  } else if (value === 'false') {
    return false;
  } else {
    return null
  }

}

function prepareBetweenValue(value) {

  let values = value.split(',')
  let obj = {}
  obj.whereQuery = ''
  obj.whereParams = []

  if (values.length === 2) {
    obj.whereQuery = ' ? and ? '
    obj.whereParams.push(values[0])
    obj.whereParams.push(values[1])
  }

  //console.log('prepareBetweenValue', obj);

  return obj;
}


function replaceWhereParamsToQMarks(openParentheses, str, comparisonOperator, condType) {

  let converted = ''

  if (openParentheses) {
    for (var i = 0; i < str.length; ++i) {
      if (str[i] === '(') {
        converted += '('
      } else {
        converted += '??'
        break;
      }
    }
  } else {

    if (comparisonOperator !== ' in ' && comparisonOperator !== ' between ' && condType !== ' on ') {
      converted = '?'
    } else if (condType === ' on ') {
      converted = '??'
    }

    for (var i = str.length - 1; i >= 0; --i) {
      if (str[i] === ')') {
        converted += ')'
      } else {
        break;
      }
    }

  }

  return converted;
}

function getComparisonOperator(operator) {

  switch (operator) {

    case 'eq':
      return '='
      break;

    case 'ne':
      return '!='
      break;

    case 'lt':
      return '<'
      break;

    case 'lte':
      return '<='
      break;

    case 'gt':
      return '>'
      break;

    case 'gte':
      return '>='
      break;

    case 'is':
      return ' is '
      break;

    case 'isnot':
      return ' is not '
      break;

    // case 'isnull':
    //   return ' is NULL '
    //   break;

    // case 'isnnull':
    //   return ' is not NULL '
    //   break;

    case 'like':
      return ' like '
      break;

    case 'nlike':
      return ' not like '
      break;

    case 'in':
      return ' in '
      break;

    case 'bw':
      return ' between '
      break;

    default:
      return null
      break;

  }

}


function getLogicalOperator(operator) {

  switch (operator) {

    case '~or':
      return 'or'
      break;

    case '~and':
      return 'and'
      break;

    // case '~not':
    //   return 'not'
    //   break;

    case '~xor':
      return 'xor'
      break;

    default:
      return null
      break;
  }

}


exports.getConditionClause = function (whereInQueryParams, condType = 'where') {

  let whereQuery = '';
  let whereParams = [];
  let grammarErr = 0;
  let numOfConditions = whereInQueryParams.split(/~or|~and|~not|~xor/);
  let logicalOperatorsInClause = whereInQueryParams.match(/(~or|~and|~not|~xor)/g)

  if (numOfConditions && logicalOperatorsInClause && numOfConditions.length !== logicalOperatorsInClause.length + 1) {
    console.log('conditions and logical operators mismatch', numOfConditions.length, logicalOperatorsInClause.length);
  } else {
    //console.log('numOfConditions',numOfConditions,whereInQueryParams);
    //console.log('logicalOperatorsInClause',logicalOperatorsInClause);

    for (var i = 0; i < numOfConditions.length; ++i) {

      let variable = ''
      let comparisonOperator = ''
      let logicalOperator = ''
      let variableValue = ''
      let temp = ''

      // split on commas
      var arr = numOfConditions[i].split(',');

      // consider first two splits only
      var result = arr.splice(0, 2);

      // join to make only 3 array elements
      result.push(arr.join(','));

      // variable, operator, variablevalue
      if (result.length !== 3) {
        grammarErr = 1;
        break;
      }

      /**************** START : variable ****************/
      //console.log('variable, operator, variablevalue',result);
      variable = result[0].match(/\(+(.*)/);

      //console.log('variable',variable);

      if (!variable || variable.length !== 2) {
        grammarErr = 1;
        break;
      }

      // get the variableName and push
      whereParams.push(variable[1])

      // then replace the variable name with ??
      temp = replaceWhereParamsToQMarks(true, result[0], ' ignore ', condType)
      if (!temp) {
        grammarErr = 1;
        break;
      }
      whereQuery += temp

      /**************** END : variable ****************/


      /**************** START : operator and value ****************/
      comparisonOperator = getComparisonOperator(result[1])
      if (!comparisonOperator) {
        grammarErr = 1;
        break;
      }
      whereQuery += comparisonOperator

      // get the variableValue and push to params
      variableValue = result[2].match(/(.*?)\)/)
      if (!variableValue || variableValue.length !== 2) {
        grammarErr = 1;
        break;
      }

      if (comparisonOperator === ' in ') {
        let obj = prepareInClauseParams(variableValue[1])
        whereQuery += obj.whereQuery
        whereParams = whereParams.concat(obj.whereParams)
      } else if (comparisonOperator === ' like ' || comparisonOperator === ' not like ') {
        whereParams.push(prepareLikeValue(variableValue[1]))
      } else if (comparisonOperator === ' is ') {
        whereParams.push(prepareIsValue(variableValue[1]))
      } else if (comparisonOperator === ' between ') {
        let obj = prepareBetweenValue(variableValue[1])
        whereQuery += obj.whereQuery
        whereParams = whereParams.concat(obj.whereParams)
        //console.log(whereQuery, whereParams);
      } else {
        whereParams.push(variableValue[1])
      }

      // then replace the variableValue with ?
      temp = replaceWhereParamsToQMarks(false, result[2], comparisonOperator, condType)
      if (!temp) {
        grammarErr = 1;
        break;
      }
      whereQuery += temp

      if (numOfConditions.length !== -1 && i !== numOfConditions.length - 1) {
        //console.log('finding logical operator for',logicalOperatorsInClause[i]);
        logicalOperator = getLogicalOperator(logicalOperatorsInClause[i])

        if (!logicalOperator) {
          grammarErr = 1;
          break;
        }

        whereQuery += getLogicalOperator(logicalOperatorsInClause[i])
      }
      /**************** END : operator ****************/


    }
  }

  let obj = {}

  obj['query'] = ''
  obj['params'] = []
  obj['err'] = grammarErr

  // console.log(whereInQueryParams);
  // console.log(whereQuery);
  // console.log(whereParams);
  // console.log(grammarErr);
  // console.log('= = = = = = = = =');

  if (!grammarErr) {
    obj['query'] = whereQuery
    obj['params'] = whereParams
  }

  return obj

}
